#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace ThreadModule;

int g_ticket = 10000;
static const int SIZE = 5;

struct ThreadData
{
    std::string _threadName;
    int& _tickets;
    int _total;
    pthread_mutex_t& _mutex;

    ThreadData(const std::string name, int& ticket, pthread_mutex_t& mutex)
        :_threadName(name), _tickets(ticket), _total(0), _mutex(mutex)
    {}
};

void threadrun(ThreadData* td)
{
    // std::cout << "gticket : " << &td->_tickets << std::endl;
    // std::cout << "mutex : " << &td->_mutex << std::endl;
    while(true)
    {
        LockGuard lg(td->_mutex); //匿名对象，生命周期只有所在的一行
        if(td->_tickets > 0)
        {
            usleep(1000);
            td->_total++;
            td->_tickets--;
            std::cout << td->_threadName << " get a ticket : " << td->_tickets + 1 << std::endl;
        }
        else
            break;
    }
}


int main()
{
    std::vector<Thread<ThreadData*>> threads;
    std::vector<ThreadData*> datas;
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);
    for (int i = 0; i < SIZE; i++)
    {
        char buff[128];
        snprintf(buff, sizeof buff, "thread-%d", i + 1);
        ThreadData* td = new ThreadData(buff, g_ticket, mutex);
        threads.emplace_back(threadrun, td, buff);
        datas.emplace_back(td);
    }

    for (auto& thread : threads)
        thread.Start();

    for (auto& thread : threads)
        thread.Join();

    for (auto& td : datas)
    {
        std::cout << td->_threadName << " total tickets : " << td->_total << std::endl;
        delete td;
    }

    pthread_mutex_destroy(&mutex);
    return 0;
}












// pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
//数据不一致问题

// 1.自己手动控制
// void buyticket(int& tickets)
// {
//     while(true)
//     {
//         pthread_mutex_lock(&gMutex);
//         if(tickets > 0)
//         {
//             int tmp = tickets;
//             usleep(1000);
//             tickets--;
//             pthread_mutex_unlock(&gMutex);

//             printf("get tickets : %d\n", tmp);
//         }
//         else
//         {
//             pthread_mutex_unlock(&gMutex);
//             break;
//         }
//     }
// }

// 2.使用lockguard
// void buyticket(int& tickets)
// {
//     while(true)
//     {
//         LockGuard lg(gMutex);
//         if(tickets > 0)
//         {
//             int tmp = tickets;
//             usleep(1000);
//             tickets--;
//             printf("get tickets : %d\n", tmp);
//         }
//         else
//         {
//             break;
//         }
//     }
// }

// int main()
// {
//     std::vector<Thread<int>> threads;
//     for (int i = 0; i < 5; i++)
//     {
//         threads.emplace_back(buyticket, g_ticket);
//     }
//     for (auto& thread : threads)
//         thread.Start();
//     for (auto& thread : threads)
//         thread.Join();

//     return 0;
// }